#-*- coding: utf-8 -*-

import wxversion
wxversion.select('2.8')
import wx,sys

from pandac.PandaModules import *
from direct.showbase import DirectObject
import pmcore.basecom

class ToolbarControl():
    btns = {}
    mw = None
    #def __init__(self,mw):
    #    self.mw = mw
    def _set_main_window(self,mw):
        self.mw = mw
        
    def add_btn(self,name,bmp,btn_callback,args = None):
        if self.mw:
            bid = self.mw.frame_1_toolbar.AddLabelTool(-1,name,wx.Bitmap(bmp))
            self.btns[bid.GetId()] = (name, btn_callback, args)
            self.mw.Bind(wx.EVT_TOOL, self._onToolbar)
            self.mw.frame_1_toolbar.Realize()
            self.mw.SendSizeEvent()
            self.mw.Update()
        else:
            print "ERROR: Sample wx frame: Main Window not ready"
            
    def _onToolbar(self,evt):
        name, cb, args = self.btns[evt.GetId()]
        if cb:
            cb(args)

class MenuControl():
    menus = {}
    mitems = {}
    mw = None
    
    def _set_main_window(self,mw):
        self.mw = mw
        
    def add_menu_item(self,path,m_callback,args=None):
        if self.mw:
            path = path.split("->")
            if path[0] not in self.menus.keys():
                m = wx.Menu()
                self.menus[path[0]] = m
                self.mw.frame_1_menubar.Append(m, path[0])
            mi = wx.MenuItem(self.menus[path[0]], wx.NewId(), path[1], "", wx.ITEM_NORMAL)
            self.mitems[mi.GetId()] = (mi,m_callback,args)
            self.menus[path[0]].AppendItem(mi)
            self.mw.Bind(wx.EVT_MENU, self._onMenu, mi)
        else:
            print "ERROR: Sample wx frame: Main Window not ready"
            
    def _onMenu(self,evt):
        if self.mitems.has_key(evt.GetId()):
            name, cb, args = self.mitems[evt.GetId()]
            if cb:
                cb(args)
        else:
            print "ERROR: wxframe, key error"

class FileDialog():
    def __init__(self,wc=None):
        if not wc:
            self.wildcard = "All files (*.*)|*.*"
        else:
            self.wildcard = wc

    def open(self,multiple = True,dtype = "Open"):
        paths = None
        #dstyle = wx.OPEN | wx.MULTIPLE | wx.CHANGE_DIR
        dstyle = wx.CHANGE_DIR
        if multiple and dtype == "Open":
            dstyle |= wx.MULTIPLE            
        if dtype == "Open":
            dstyle |= wx.OPEN
        else:
            dstyle |= wx.SAVE
            
        dlgf = wx.FileDialog(None, message="Change model:", defaultDir='',
                             defaultFile="", wildcard=self.wildcard, 
                             style=dstyle
                            )
        dlgf.Show(True)
        if dlgf.ShowModal() == wx.ID_OK:
            paths = dlgf.GetPaths()
        dlgf.Destroy()
        return paths


class TabControl():
    tabs = {}
    mw = None
    elements = {}
    
    def _set_main_window(self,mw):
        self.mw = mw
    
    def add_tab(self,name):
        if self.mw:
            if name not in self.tabs.keys():
                p = wx.Panel(self.mw.notebook_1,-1)
                s = wx.BoxSizer(wx.VERTICAL)
                self.mw.notebook_1.AddPage(p, name)
                p.SetSizer(s)
                self.tabs[name] = (p,s)
                self.mw.Layout()
        else:
            print "ERROR: Sample wx frame: Main Window not ready"
            
    def add_element(self,element,tabname):
        if tabname in self.tabs.keys():
            if not self.elements.has_key(tabname):
                self.elements[tabname] = []
            self.elements[tabname].append(element)
            p,s = self.tabs[tabname]
            element.Reparent(p)
            s.Add(element)
            s.Layout()
        else:
            print "ERROR: Sample wx frame: Tab %s not exist" % tabname

class TextButton():
    mw = None
    
    def _set_main_window(self,mw):
        self.mw = mw
    
    def new(self,name,callback):
        res = wx.Button(self.mw,wx.NewId(),name)
        self.mw.Bind(wx.EVT_BUTTON,callback,res)
        return res

class InputFieldBase(wx.BoxSizer):
    def __init__(self, *args, **kwargs):
        #self._sizer = wx.BoxSizer(wx.HORIZONTAL)
        if kwargs.has_key("parent"):
            parent = kwargs["parent"]
            del kwargs["parent"]
        else:
            print "ERROR: InputFilel need parent"
            sys.exit()
        wx.BoxSizer.__init__(self, *args, **kwargs)
        self._field = wx.TextCtrl(parent,-1,"")
        self._label = wx.StaticText(parent, -1, "")
        self.Add(self._label)
        self.Add(self._field)
        self.Layout()
        
    def Reparent(self,p):
        self._field.Reparent(p)
        self._label.Reparent(p)
        
    def _set_value(self,value):
        self._field.SetValue(u"%s"%value)
        
    def _get_value(self):
        return self._field.GetValue()
    
    def _set_label(self,value):
        self._label.SetLabel(u"%s"%value)
        
    def _get_label(self):
        return self._label.GetLabel()
        
    value = property(fset = _set_value, fget = _get_value)
    label = property(fset = _set_label, fget = _get_label)
        
class InputField():
    mw = None
    
    def _set_main_window(self,mw):
        self.mw = mw
    
    def new(self, label, onText = None):
        res = InputFieldBase(wx.HORIZONTAL, parent = self.mw)
        res.label = label
        if onText:
            self.mw.Bind(wx.EVT_TEXT,onText,res._field)
        return res

class SampleWxFrame (pmcore.basecom.BaseComponent):
    name = "Sample wx frame"
    version = "0.1.4"
    weight = -10
    tbctrl = ToolbarControl()
    mnuctrl = MenuControl()
    filedlg = FileDialog()
    txtbtn = TextButton()
    tabctrl = TabControl()
    inpfield = InputField()
    
    provides = (
        #-----------------
        {"name":"toolbar-control",
        "description":u"",
        "help":u"",
        "value":tbctrl,"version":"0.1"},
        #-----------------
        {"name":"menu-control",
        "description":u"",
        "help":u"",
        "value":mnuctrl,"version":"0.1"},
        #-----------------
        {"name":"file-dialog",
        "description":u"",
        "help":u"",
        "value":filedlg,"version":"0.1"},
        #-----------------
        {"name":"text-button",
        "description":u"",
        "help":u"",
        "value":txtbtn,"version":"0.1"},
        #-----------------
        {"name":"tab-control",
        "description":u"",
        "help":u"",
        "value":tabctrl,"version":"0.1"},
        #-----------------
        {"name":"input-field",
        "description":u"",
        "help":u"",
        "value":inpfield,"version":"0.1"}
    )
        
    def __init__(self):
        pmcore.basecom.BaseComponent.__init__(self)
    
    def before_direct_import(self):
        loadPrcFileData("", "window-type none")

    def after_direct_import(self):
        self.frame = EditorApp()        
        self.tbctrl._set_main_window(self.frame.MainWindow)
        self.mnuctrl._set_main_window(self.frame.MainWindow)
        self.txtbtn._set_main_window(self.frame.MainWindow)
        self.tabctrl._set_main_window(self.frame.MainWindow)
        self.inpfield._set_main_window(self.frame.MainWindow)


        
        
class MyFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        # begin wxGlade: MyFrame.__init__
        kwds["style"] = wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)
        self.notebook_1 = wx.Notebook(self, -1, style=0)
        self.panel_1 = P3dViewport(self, -1)
        
        # Tool Bar
        self.frame_1_toolbar = wx.ToolBar(self, -1)
        self.SetToolBar(self.frame_1_toolbar)
        # Tool Bar end
        self.frame_1_statusbar = self.CreateStatusBar(1, 0)
        
        # Menu Bar
        self.frame_1_menubar = wx.MenuBar()
        #self.mFile = wx.Menu()
        #self.mExit = wx.MenuItem(self.mFile, wx.NewId(), "Exit", "", wx.ITEM_NORMAL)
        #self.mFile.AppendItem(self.mExit)
        #self.frame_1_menubar.Append(self.mFile, "File")
        self.SetMenuBar(self.frame_1_menubar)
        # Menu Bar end

        self.__set_properties()
        self.__do_layout()
        # end wxGlade
        #self.Bind(wx.EVT_MENU, self.exitProgram, self.mExit)
        self.Bind(wx.EVT_CLOSE, self.onCloseWindow)
        self.SetAutoLayout(1)

    def __set_properties(self):
        # begin wxGlade: MyFrame.__set_properties
        self.SetTitle("frame_1")
        #self.SetSize((848, 661))
        self.frame_1_toolbar.Realize()
        self.frame_1_statusbar.SetStatusWidths([-1])
        # statusbar fields
        frame_1_statusbar_fields = ["frame_1_statusbar"]
        for i in range(len(frame_1_statusbar_fields)):
            self.frame_1_statusbar.SetStatusText(frame_1_statusbar_fields[i], i)
        # end wxGlade

    def __do_layout(self):
        # begin wxGlade: MyFrame.__do_layout
        sizer_2 = wx.BoxSizer(wx.HORIZONTAL)
        sizer_2.Add(self.panel_1, 3, wx.EXPAND, 0)
        #self.notebook_1.AddPage(self.notebook_1_pane_1, "tab1")
        sizer_2.Add(self.notebook_1, 1, wx.EXPAND, 0)
        self.SetSizer(sizer_2)
        sizer_2.SetSizeHints(self)
        self.SetSize((848, 661))
        self.Layout()
        # end wxGlade
        
    def exitProgram(self, event): # wxGlade: MainFrame.<event_handler>
        self.Close();
        sys.exit();  
        
    def onCloseWindow(self,event):
        sys.exit();
    
    def add_tab(self):
        self.p = wx.Panel(self.notebook_1,-1)
        #self.frame.MainWindow.Layout()
        
        
class P3dViewport(wx.Panel):
  # this panel contains the panda 3d window
  def __init__(self, *args, **kwargs):
    wx.Panel.__init__(self, *args, **kwargs)

  def initialize(self):
    # the panda3d window must be put into the panel after the wx-window has
    # been created
    assert self.GetHandle() != 0

    # put the panda3d
    wp = WindowProperties()
    wp.setOrigin(0, 0)
    wp.setSize(self.ClientSize.GetWidth(), self.ClientSize.GetHeight())
    wp.setParentWindow(self.GetHandle())
    base.openDefaultWindow(props = wp, gsg = None)

    # attach the resize event
    wx.EVT_SIZE(self, self.OnResize)

  def OnResize(self, event):
    # when the wx-panel is resized, fit the panda3d window into it
    frame_size = event.GetSize()
    wp = WindowProperties()
    wp.setOrigin(0, 0)
    wp.setSize(frame_size.GetWidth(), frame_size.GetHeight())
    base.win.requestProperties(wp)
    

class EditorApp(DirectObject.DirectObject):
  def __init__(self):

    self.wxApp = wx.App(redirect = False)
    self.wxApp.SetAppName("Panda Editor")
    self.wxApp.SetClassName("PEditor")

    self.appInit()
    self.MainWindow = MyFrame(None, -1, "")
    self.wxApp.SetTopWindow(self.MainWindow)
    self.MainWindow.Show() 
    # update the wx-window and run a step (window created?)
    self.MainWindow.Update()
    self.wxStep()
    # update the p3d window
    self.MainWindow.panel_1.initialize()

    # do something with the panda3d view
    #loader.loadModel('environment').reparentTo(render)



  def appInit(self):
    # Create a new event loop (to overide default wxEventLoop)
    self.evtLoop = wx.EventLoop()
    self.oldLoop = wx.EventLoop.GetActive()
    wx.EventLoop.SetActive(self.evtLoop)
    taskMgr.add(self.wxStep, "evtLoopTask")

  def onDestroy(self, evt):
    # called on wx window destroy
    wx.EventLoop.SetActive(self.oldLoop)
   
  def quit(self,event):
    self.onDestroy(event)
      # to close Panda
    try:
      base
    except NameError:
      sys.exit()       
    base.userExit()

  def wxStep(self, task = None):
    # process the events wx sends
    while self.evtLoop.Pending():
      self.evtLoop.Dispatch()
    self.wxApp.ProcessIdle()
    if task != None: return task.cont
    
